package pers.llc.css.nio.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * https://blog.csdn.net/lucky_ly/article/details/79052455
 *https://blog.csdn.net/u010393325/article/details/82463048
 * @author fancy
 * @time 2019/3/31 0031 13:54
 */
public class SocketChannelClient {



    public ArrayBlockingQueue<String> arrayQueue = new ArrayBlockingQueue<>(8);
    static Charset charset = Charset.forName("UTF-8");
    private static Selector selector = null;
    private volatile static boolean stop = false;
    private static SocketChannel channel = null;

    public static void init() {
        initSelector();
        initSocketChannel();
        run();
    }

    public static void initSelector() {
        try {
            selector = Selector.open();
        } catch (IOException e) {
        }
    }

    public static void initSocketChannel() {
        try {
            channel = SocketChannel.open();
            channel.configureBlocking(false);
            channel.connect(new InetSocketAddress("127.0.0.1", 7777));
            channel.register(selector, SelectionKey.OP_CONNECT);
        } catch (ClosedChannelException e) {
        } catch (IOException e) {
        }
    }

    public static void run() {
        try {
            while (!stop) {
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectedKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    handle(key);
                    iterator.remove();
                }

            }
        } catch (IOException e) {
        }
    }

    public static void handle(SelectionKey key) throws IOException {
        try {
            if (key.isConnectable()) {
                handleConnectable(key);
            }
            if (key.isReadable()) {
                handelReadable(key);
            }
        } catch (Exception e) {
            key.cancel();
            if (key.channel() != null) {
                try {
                    key.channel().close();
                } catch (IOException e1) {
                }
            }
        }
    }

    private static void handelReadable(SelectionKey key) throws IOException {
        SocketChannel sc = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int temp = sc.read(buffer);
        String content = "收到Servero数据: ";
        if (temp > 0) {
            buffer.flip();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            content += new String(bytes);
            System.out.println(" " + content);
        }
    }

    private static void handleConnectable(SelectionKey key) throws IOException {
        SocketChannel sc = (SocketChannel) key.channel();
        if (sc.finishConnect()) {
            sc.register(selector, SelectionKey.OP_READ);
        }
        new Thread(() -> {
            try {
                while (true) {
                    input(sc);
                }
            } catch (IOException e) {
            }
        }).start();
    }

    public static void input(SocketChannel channel) throws IOException {
        ReadableByteChannel source = Channels.newChannel(System.in);
        ByteBuffer bytebuffer = ByteBuffer.allocateDirect(1024);
        while (source.read(bytebuffer) != -1) {
            bytebuffer.flip();
            while (bytebuffer.hasRemaining()) {
                channel.write(bytebuffer);
            }
            bytebuffer.clear();
            System.out.println("发送信息完成");
        }
    }

    public static void main(String[] args) {
        SocketChannelClient.init();
    }
}
